/*************************************************
    Author: Minh B. Do (ASU - binhminh@asu.edu)
 **************************************************/
package edu.asu.sapa.lifted;

import edu.asu.sapa.Planner;
import edu.asu.sapa.ground.MathForm;

/**
 * MathForm: Represent the abstract template class parsed from the domain
 * file. Used to make ground math form (stored in GMathForm). Structurally
 * similar to GMathForm. Refer to that class for member functions.
 */
public class LiftedMathForm {
	public static final LiftedMathForm Zero = new LiftedMathForm(0f);
	public static final LiftedMathForm One = new LiftedMathForm(1f);
	public static final LiftedMathForm Epsilon = new LiftedMathForm(Planner.EPSILON);
	public static final LiftedMathForm TwoEpsilon = new LiftedMathForm(2 * Planner.EPSILON);
	public static final LiftedMathForm NInf = new LiftedMathForm(Float.NEGATIVE_INFINITY);
	public static final LiftedMathForm PInf = new LiftedMathForm(Float.POSITIVE_INFINITY);

	public static final LiftedMathForm StartRef = new LiftedMathForm(MathForm.Start);
	public static final LiftedMathForm DurRef = new LiftedMathForm(MathForm.Duration);
	public static final LiftedMathForm EndRef = new LiftedMathForm(MathForm.End);

	public int type;  
	public float value;  
	public Function fluent; 

	public char op; // +, -, *, /

	public LiftedMathForm left;
	public LiftedMathForm right;

	public LiftedMathForm(int type) {
		this.type = type;
	}

	public LiftedMathForm(char op, LiftedMathForm l, LiftedMathForm r) {
		type = MathForm.Operator;
		this.op = op;
		left = l;
		right = r;
	}

	public LiftedMathForm(float v) {
		type = MathForm.Constant;
		value = v;
	}

	public LiftedMathForm(Function f) {
		type = MathForm.Fluent;
		fluent = f;
	}

	public void setType(int b) {
		type = b;
	}

	public int getType() {
		return type;
	}

	public void setValue(float f) {
		value = f;
	}

	public float getValue() {
		return value;
	}

	public void setElement(Function e) {
		fluent = e;
	}

	public Function getElement() {
		return fluent;
	}

	public void setOperator(char c) {
		op = c;
	}

	public char getOperator() {
		return op;
	}

	public void setLeft(LiftedMathForm m) {
		left = m;
	}

	public LiftedMathForm getLeft() {
		return left;
	}

	public void setRight(LiftedMathForm m) {
		right = m;
	}

	public LiftedMathForm getRight() {
		return right;
	}

	public String toString() {
		if( type == MathForm.Fluent )
			return "(" + fluent.toString() + ")";

		if( type == MathForm.Constant)
			return Float.toString(value);

		if( type == MathForm.DT )
			return "#t";

		if (type == MathForm.Start)
			return "start";

		if (type == MathForm.Duration)
			return "?duration";
		
		if (type == MathForm.End)
			return "end";

		if (type == MathForm.Operator)
			return "(" +  op + " " + left.toString() 
			+ " " + right.toString() + ")";

		return "unknown type: " + type;
	}
}
